<template>
	<!-- CHANGE CODE paddingTop -->
	<view
		class="u-input"
		:class="{
			'u-input--border': border,
			'u-input--error': validateState
		}"
		:style="{
			padding: `0 ${border ? 20 : 0}rpx`,
			borderColor: borderColor,
			textAlign: inputAlign,
			paddingTop: type == 'textarea' ? '10rpx' : (inputAlign == 'right' ? '0' : '10rpx'),
			'--main-color': $theme.mainColor,
			'--primary-light': $theme.primaryLight,
			'--light-color': $theme.lightColor,
			'--error': $theme.error
		}"
		@tap.stop="inputClick"
	>
		<!-- CHANGE CODE style-->
		<textarea
			v-if="type == 'textarea'"
			:class="['u-input__input', 'u-input__textarea', disabled ? 'u-input-disabled' : ''] "
			:style="[getStyle]" 
			:value="value"
			:placeholder="placeholder"
			:placeholderStyle="'color:' + myPlaceholderStyle"
			:disabled="disabled"
			:maxlength="inputMaxlength"
			:fixed="fixed"
			:focus="focus"
			:autoHeight="autoHeight"
			@input="handleInput"
			@blur="handleBlur"
			@focus="onFocus"
			@confirm="onConfirm"
		/>
		<!-- CHANGE CODE style-->
		<input
			v-else
			:class="['u-input__input', type == 'password' ? 'u-input__padding-right' : '', disabled ? 'u-input-disabled' : '']"
			:type="type == 'password' ? 'text' : type"
			:style="[getStyle]"
			:value="defaultValue"
			:password="type == 'password' && !showPassword"
			:placeholder="placeholder"
			:placeholderStyle="'color:' + myPlaceholderStyle"
			:disabled="disabled || type === 'select'"
			:maxlength="inputMaxlength"
			:focus="focus"
			:confirmType="confirmType"
			@focus="onFocus"
			@blur="handleBlur"
			@input="handleInput"
			@confirm="onConfirm"
		/>
		<view class="u-input__right-icon u-flex">
			<view class="u-input__right-icon__clear u-input__right-icon__item" v-if="clearable && value && focused">
				<w-icon size="32" name="close-circle-fill" :color="myPlaceholderStyle" @touchstart="onClear"/>
			</view>
			<view class="u-input__right-icon__clear u-input__right-icon__item" v-if="passwordIcon && type == 'password'">
				<w-icon top="8" size="32" :name="!showPassword ? 'eye' : 'eye-fill'" :color="myPlaceholderStyle" @click="showPassword = !showPassword"/>
			</view>
			<view class="u-input__right-icon--select u-input__right-icon__item" v-if="type == 'select'" :class="{
				'u-input__right-icon--select--reverse': selectOpen
			}">
				<w-icon name="arrow-down-fill" size="26" :color="myPlaceholderStyle"></w-icon>
			</view>
		</view>
		<!-- ADD CODE textarea专有计数器 -->
		<view class="u-input__mm-input-count" v-if="type == 'textarea' && inputCount">
			<text class="u-input__mm-input-count__current" :style="{color: $theme.primary}">{{ value.length }}</text>
			<text>/</text>
			<text class="u-input__mm-input-count__limit">{{ inputMaxlength }}</text>
		</view>
		<!-- END -->
	</view>
</template>

<script>
	import Emitter from '../../libs/util/emitter.js';
	/**
	 * input 输入框
	 * @description 此组件为一个输入框，默认没有边框和样式，是专门为配合表单组件u-form而设计的，利用它可以快速实现表单验证，输入内容，下拉选择等功能。
	 * @tutorial http://uviewui.com/components/input.html
	 * @property {String} type 模式选择，见官网说明
	 * @property {Boolean} clearable 是否显示右侧的清除图标(默认true)
	 * @property {} v-model 用于双向绑定输入框的值
	 * @property {String} input-align 输入框文字的对齐方式(默认left)
	 * @property {String} placeholder placeholder显示值(默认 '请输入内容')
	 * @property {Boolean} disabled 是否禁用输入框(默认false)
	 * @property {String Number} maxlength 输入框的最大可输入长度(默认140)
	 * @property {String} placeholderStyle placeholder的样式，字符串形式，如"color: red;"(默认 "color: #c0c4cc;")
	 * @property {String} confirm-type 设置键盘右下角按钮的文字，仅在type为text时生效(默认done)
	 * @property {Object} custom-style 自定义输入框的样式，对象形式
	 * @property {Boolean} focus 是否自动获得焦点(默认false)
	 * @property {Boolean} fixed 如果type为textarea，且在一个"position:fixed"的区域，需要指明为true(默认false)
	 * @property {Boolean} password-icon type为password时，是否显示右侧的密码查看图标(默认true)
	 * @property {Boolean} border 是否显示边框(默认false)
	 * @property {String} border-color 输入框的边框颜色(默认#dcdfe6)
	 * @property {Boolean} auto-height 是否自动增高输入区域，type为textarea时有效(默认true)
	 * @property {String Number} height 高度，单位rpx(text类型时为70，textarea时为100)
	 * @example <u-input v-model="value" :type="type" :border="border" />
	 */
	export default {
		name: 'w-input',
		mixins: [Emitter],
		props: {
			value: {
				type: String,
				default: ''
			},
			// 输入框的类型，textarea，text，number
			type: {
				type: String,
				default: 'text'
			},
			inputAlign: {
				type: String,
				default: 'right'
			},
			placeholder: {
				type: String,
				default: '请输入内容'
			},
			disabled: {
				type: Boolean,
				default: false
			},
			maxlength: {
				type: [Number, String],
				default: 140
			},
			placeholderStyle: {
				type: String,
				default: 'color: #c0c4cc;'
			},
			confirmType: {
				type: String,
				default: 'done'
			},
			// 输入框的自定义样式
			customStyle: {
				type: Object,
				default() {
					return {};
				}
			},
			// 如果 textarea 是在一个 position:fixed 的区域，需要显示指定属性 fixed 为 true
			fixed: {
				type: Boolean,
				default: false
			},
			// 是否自动获得焦点
			focus: {
				type: Boolean,
				default: false
			},
			// 密码类型时，是否显示右侧的密码图标
			passwordIcon: {
				type: Boolean,
				default: true
			},
			// input|textarea是否显示边框
			border: {
				type: Boolean,
				default: false
			},
			// 输入框的边框颜色
			borderColor: {
				type: String,
				default: '#dcdfe6'
			},
			autoHeight: {
				type: Boolean,
				default: true
			},
			// type=select时，旋转右侧的图标，标识当前处于打开还是关闭select的状态
			// open-打开，close-关闭
			selectOpen: {
				type: Boolean,
				default: false
			},
			// 高度，单位rpx
			height: {
				type: [Number, String],
				default: ''
			},
			// 是否可清空
			clearable: {
				type: Boolean,
				default: false
			},
			inputCount: {
				type: Boolean,
				default: true
			}
		},
		data() {
			return {
				defaultValue: this.value,
				inputHeight: 60, // input的高度
				textareaHeight: 140, // textarea的高度
				validateState: false, // 当前input的验证状态，用于错误时，边框是否改为红色
				focused: false, // 当前是否处于获得焦点的状态
				showPassword: false, // 是否预览密码
				marginRight: 0, // 输入框右边的距离，当获得焦点时各一个后面的距离，避免点击右边图标误触输入框
				myPlaceholderStyle: ''
			};
		},
		watch: {
			value(nVal, oVal) {
				this.defaultValue = nVal;
				// 当值发生变化，且为select类型时(此时input被设置为disabled，不会触发@input事件)，模拟触发@input事件
				if(nVal != oVal && this.type == 'select') this.handleInput({
					detail: {
						value: nVal
					}
				})
			},
			focused(nVal) {
				if(this.clearable && this.value) {
					this.getMarginRight();
				}
			}
		},
		computed: {
			// 因为uniapp的input组件的maxlength组件必须要数值，这里转为数值，给用户可以传入字符串数值
			inputMaxlength() {
				return Number(this.maxlength);
			},
			getStyle() {
				let style = {};
				// 如果没有自定义高度，就根据type为input还是textare来分配一个默认的高度
				style.minHeight = this.height ? this.height + 'rpx' : this.type == 'textarea' ? 
					this.textareaHeight + 'rpx' : this.inputHeight + 'rpx';
				style.marginRight = this.marginRight + 'px';
				style = Object.assign(style, this.customStyle);
				return style;
			}
		},
		created() {
			this.myPlaceholderStyle = this.$theme.lightColor;
			// 监听u-form-item发出的错误事件，将输入框边框变红色
			this.$on('on-form-item-error', this.onFormItemError);
		},
		mounted() {
			this.getMarginRight();
		},
		methods: {
			// 计算输入框的右边距
			getMarginRight() {
				this.$nextTick(() => {
					const query = uni.createSelectorQuery().in(this);
					query.select('.u-input__right-icon').boundingClientRect(data => {
						// 此处20rpx为图标绝对定位右侧的“right”
						this.marginRight = data.width + uni.upx2px(20);
					}).exec();
				})
			},
			/**
			 * change 事件
			 * @param event
			 */
			handleInput(event) {
				// 当前model 赋值
				this.defaultValue = event.detail.value;
				// vue 原生的方法 return 出去
				this.$emit('input', event.detail.value);
				// 过一个生命周期再发送事件给u-form-item，否则this.$emit('input')更新了父组件的值，但是微信小程序上
				// 尚未更新到u-form-item，导致获取的值为空，从而校验混论
				this.$nextTick(() => {
					// 将当前的值发送到 u-form-item 进行校验
					this.dispatch('w-form-item', 'on-form-change', event.detail.value);
				});
			},
			/**
			 * blur 事件
			 * @param event
			 */
			handleBlur(event) {
				this.focused = false;
				// vue 原生的方法 return 出去
				this.$emit('blur', event.detail.value);
				this.$nextTick(() => {
					// 将当前的值发送到 u-form-item 进行校验
					this.dispatch('w-form-item', 'on-form-blur', event.detail.value);
				});
			},
			onFormItemError(status) {
				this.validateState = status;
			},
			onFocus(event) {
				this.focused = true;
				this.$emit('focus');
			},
			onConfirm(e) {
				this.$emit('confirm', e.detail.value);
			},
			onClear(event) {
				this.$emit('input', '');
			},
			inputClick() {
				this.$emit('click');
			}
		}
	};
</script>

<style lang="scss" scoped>
@import '../../libs/css/variable.scss';
.u-input {
	position: relative;
	flex: 1;
	
	&__input {
		//height: $u-form-item-height;
		font-size: 28rpx;
		color: var(--main-color);
		
		// ADD CODE
		margin-right: 0!important;
		// END
	}
	
	&__textarea {
		width: auto;
		font-size: 28rpx;
		color: var(--main-color);
		padding: 10rpx 0;
		line-height: 40rpx;
		// CHANGE CODE
		background-color: var(--primary-light);
		padding: 15rpx 20rpx;
		// #ifdef MP-WEIXIN
		padding: 8rpx 20rpx;
		// #endif
		// min-height: 140rpx;
		text-align: left;
		// height: 140rpx;
		// END
	}
	.u-input-disabled {
		color: var(--light-color);
	}

	&--border {
		border-radius: 6rpx;
		border-radius: 4px;
		border: 1px solid $form-item-border-color;
	}
	
	&--error {
		border-color: var(--error)!important;
	}
	
	&__right-icon {
		position: absolute;
		// CHANGE CODE
		right: 5rpx;
		// END
		top: 50%;
		z-index: 3;
		transform: translateY(-50%);
		
		&__item {
			margin-left: 10rpx;
		}
		
		&--select {
			transition: transform .4s;
			
			&--reverse {
				transform: rotate(-180deg);
			}
		}
	}
	
	// ADD CODE
	&__mm-input-count {
		position: absolute;
		right: 0;
		top: -$form-item-height;
		font-size: 26rpx;
		color: var(--light-color);
		line-height: $form-item-height;
		height: $form-item-height;
		&__current {
			color: var(--primary);
		}
	}
	&__padding-right {
		padding-right: 50rpx;
	}
	// END
}
</style>
